<template>
  <div id="pro-table">
    <!-- 表格工具栏 -->
    <div class="pro-table-tool">
      <!-- 自定义工具栏 -->
      <div class="pro-table-prev mt-10">
        <template :key="index" v-for="(item, index) in toolbar">
          <!-- 更多按钮 -->
          <pro-authority
            :value="item.code ? item.code : false"
            v-if="item.children && item.children.length > 0"
          >
            <a-dropdown>
              <a-button @click="item.event(selectedRowKeys)">
                {{ item.label }}
              </a-button>
              <template #overlay>
                <a-menu>
                  <!-- 遍历子集 -->
                  <pro-authority
                    v-for="(child, i) in item.children"
                    :key="i"
                    :value="child.code ? item.code : false"
                  >
                    <a-menu-item>
                      <a @click="child.event(selectedRowKeys)">
                        {{ child.label }}
                      </a>
                    </a-menu-item>
                  </pro-authority>
                </a-menu>
              </template>
            </a-dropdown>
          </pro-authority>
          <pro-authority :value="item.code ? item.code : false" v-else>
            <a-button
              :type="item.type ? item.type : 'default'"
              @click="item.event(selectedRowKeys)"
            >
              {{ item.label }}
            </a-button>
          </pro-authority>
        </template>
      </div>
      <!-- 默认工具栏 -->
      <div class="pro-table-next" v-if="defaultToolBar">
        <span v-if="isShowImportAndExport">
          <a-button>
            <template #icon>
              <ImportOutlined />
            </template>
          </a-button>
          <a-button>
            <template #icon>
              <ExportOutlined />
            </template>
          </a-button>
        </span>
        <!-- 刷新工具栏 -->
        <a-button @click="reload">
          <template #icon>
            <SyncOutlined/>
          </template>
        </a-button>
        <!-- 过滤工具栏 -->
        <a-dropdown>
          <a-button>
            <template #icon>
              <AppstoreOutlined/>
            </template>
          </a-button>
          <template #overlay>
            <a-menu class="filtration">
              <a-checkbox-group
                v-model:value="filtrationColumnKeys"
                @change="filtration"
              >
                <a-row>
                  <!-- 遍历字段 -->
                  <a-col
                    :span="24"
                    :key="index"
                    v-for="(filtrationColumn, index) in filtrationColumns"
                  >
                    <a-checkbox :value="filtrationColumn.value">
                      {{ filtrationColumn.label }}
                    </a-checkbox>
                  </a-col>
                </a-row>
              </a-checkbox-group>
            </a-menu>
          </template>
        </a-dropdown>
        <!-- 过滤工具栏 -->
        <a-dropdown>
          <a-button>
            <template #icon>
              <ColumnHeightOutlined/>
            </template>
          </a-button>
          <template #overlay>
            <a-menu :selectedKeys="[size]">
              <a-menu-item @click="changeSize('default')" key="default">默认尺寸</a-menu-item>
              <a-menu-item @click="changeSize('middle')" key="middle">中等尺寸</a-menu-item>
              <a-menu-item @click="changeSize('small')" key="small">最小尺寸</a-menu-item>
            </a-menu>
          </template>
        </a-dropdown>
        <a-button @click="print">
          <template #icon>
            <ExportOutlined/>
          </template>
        </a-button>
      </div>
      <!-- 搜索框 -->
      <div class="pro-table-next mt-10" v-if="search.isSearch">
        <a-input-search
          v-model:value="state.fuzzy"
          :placeholder="search.searchTitle"
          style="width: 200px"
          @search="onSearch"
        />
      </div>
    </div>
    <!-- 表格组件 -->
    <a-table
      bordered
      rowKey="id"
      @change="fetch"
      :columns="columns"
      :loading="loading"
      :pagination="pagination"
      :dataSource="datasource"
      :row-selection="rowSelection"
      :size="size"
      :scroll="state.scroll"
      :onRowClick="(row) => { handleRow(row) }"
    >
      <!-- 列转换 -->
      <template
        :key="index"
        v-for="(column, index) in columns"
        #[column.dataIndex]="{ record }"
      >
        <!-- 行操作 -->
        <span v-if="column.dataIndex == 'operate'">
          <template :key="i" v-for="(item, i) in operate">
            <!-- 下拉操作 -->
            <a-dropdown v-if="item.children && item.children.length > 0">
              <a> {{ item.label }} </a>
              <template #overlay>
                <a-menu>
                  <!-- 遍历子集 -->
                  <pro-authority
                    v-for="(child, i) in item.children"
                    :key="i"
                    :value="child.code ? item.code : false"
                    v-show="child.show ? child.show(record) : true"
                  >
                    <a-menu-item>
                      <a @click="child.event(record)">
                        {{ child.label }}
                      </a>
                    </a-menu-item>
                  </pro-authority>
                </a-menu>
              </template>
            </a-dropdown>
            <!-- 单个操作 -->
            <pro-authority :value="item.code ? item.code : false" v-else>
              <a class="separate" :style="item.label === '删除' ? 'color: #f5222d;' : ''"
                 @click="item.event(record)" v-if="item.show ? item.show(record) : true"
              > {{ item.label }} </a>
              <!-- <a-divider type="vertical" v-if="(item.show && !item.show(record)) || i != operate.length - 1"/> -->
            </pro-authority>
          </template>
        </span>

        <!-- 开关转换 -->
        <span v-else-if="column.switch">
          <a-switch
            @change="column.switch.event($event, record)"
            :checked="record[column.dataIndex] === column.switch.yes"
          />
        </span>

        <!-- 文本转换 -->
        <span v-else-if="column.conver">
          <template v-for="(data, index) in column.conver">
            <span :key="index" v-if="data.value === record[column.dataIndex]">
              {{ data.label }}
            </span>
          </template>
        </span>

        <!-- 头像 -->
        <span v-else-if="column.avatar">
          <!-- 空头像 -->
          <a-avatar
            v-if="record[column.dataIndex] == null"
            :size="column.avatar.size"
            :shape="column.avatar.shape"
          >
            <template #icon><UserOutlined/></template>
          </a-avatar>

          <!-- 非头像 -->
          <a-avatar
            v-else
            :src="record[column.dataIndex]"
            :size="column.avatar.size"
            :shape="column.avatar.shape"
          />
        </span>

        <!-- 预览 -->
        <span v-else-if="column.image">
          <a-image
            :width="column.image.width"
            :src="record[column.dataIndex]"
          />
        </span>

        <span v-else-if="column.cellRender" :title="column.ellipsis ? column.cellRender(record, record[column.dataIndex]) : ''">
          {{ column.cellRender(record, record[column.dataIndex]) }}
        </span>


        <span v-else-if="column.ellipsis ">
          <a-tooltip placement="topLeft">
            <template #title>{{ record[column.dataIndex] }}</template>
            {{ record[column.dataIndex] }}
          </a-tooltip>
        </span>

        <!-- 原样输出 -->
        <span v-else-if="record" :title="column.ellipsis ? record[column.dataIndex] : ''">
          {{ record[column.dataIndex] }}
        </span>

      </template>
    </a-table>
  </div>
</template>
<script>
import "./index.less";
import T from "ant-design-vue/es/table/Table";
import { defineComponent, onMounted, reactive, toRefs, watch } from "vue";
import {
  AppstoreOutlined,
  ExportOutlined,
  SyncOutlined,
  UserOutlined,
  ColumnHeightOutlined,
  ImportOutlined,
} from "@ant-design/icons-vue";
import { cloneDeep } from 'lodash'

const TProps = T.props;
export default defineComponent({
  name: "pro-table",
  components: {
    ColumnHeightOutlined,
    AppstoreOutlined,
    ExportOutlined,
    SyncOutlined,
    UserOutlined,
    ImportOutlined
  },
  /// 数据来源
  props: Object.assign({}, TProps, {
    /// 扩展参数
    param: {
      type: Object,
    },
    /// 数据来源
    fetch: {
      type: Function,
      required: false,
    },
    /// 数据解析
    columns: {
      type: Array,
      required: true,
    },
    /// 头工具栏
    toolbar: {
      type: Array,
    },
    /// 行工具栏
    operate: {
      type: Array || Boolean,
      default: false,
    },
    /// 分页参数
    pagination: {
      type: [Object, Boolean],
      default: false,
    },
    rowSelection: {
      type: Object,
    },
    defaultToolBar: {
      type: Boolean,
      default: true
    },
    // 是否展示导入导出按钮
    isShowImportAndExport: {
      type: Boolean,
      default: true
    },
    operationWidth: {
      type: [String, Number],
      default: 140
    },
    scrollObj: {
      type: Object,
      default: () => {
        return { x: 800, y: 0 }
      }
    },
    search: {
      type: Object,
      default: () => {
        return {
          isSearch: false,
          searchTitle: '请输入关键字'
        }
      }
    }
  }),

  emit: ["clickRow"],

  setup(props, context) {
    /// 状态共享
    const state = reactive({
      pagination: props.pagination == false ? false : props.pagination, // 分页
      datasource: [], // 数据源
      loading: true, // 加载
      columns: props.columns, // 字段
      filtrationColumnKeys: [], // 过滤
      selectedRowKeys: [], // 选中项
      size: 'small' || props.size, // 表格大小,
      scroll: props.scrollObj,
      fuzzy: null
    });

    const updateColumns = (columns = []) => {
      if (props.operate !== false) {
        columns.push({
          dataIndex: "operate",
          key: "operate",
          title: "操作",
          fixed: "right",
          width: props.operationWidth,
          align: 'center'
        })
      }
      /// 为所有 column 新增默认 customRender 属性
      return columns.map(column => ({ ...column, slots: { customRender: column.dataIndex } }))
    }

    state.columns = updateColumns(cloneDeep(state.columns))

    /// 过滤字段
    const filtrationColumns = [];
    props.columns.forEach(function (item) {
      filtrationColumns.push({ label: item.title, value: item.key });
      state.filtrationColumnKeys.push(item.key);
    });

    /// 过滤字段
    const filtration = function (value) {
      state.columns = props.columns.filter((item) => value.includes(item.key));
      state.filtrationColumnKeys = value;
    };

    /// 选中回调
    const onSelectChange = (selectedRowKeys) => {
      state.selectedRowKeys = selectedRowKeys;
    };

    /// 数据请求
    const fetchData = async (pagination) => {
      // console.log('pagination: ', pagination);
      /// 分页处理
      if (pagination != undefined) {
        state.pagination.pageNum = pagination.current;
      }
      /// 开启加载
      state.loading = true;
      /// 请求数据
      const { total, data } = await props.fetch(
        Object.assign({}, state.pagination, {
          ...props.param,
          fuzzy: state.fuzzy || undefined,
          total: undefined
        })
      );
      /// 状态重置
      if (state.pagination != false) {
        state.pagination.total = total;
      }
      // console.log('获取到的数据',data)
      state.datasource = data;
      state.loading = false;
    };

    /// 刷新方法
    const reload = function () {
      fetchData();
    };

    /// 初始数据
    onMounted(async () => {
      await fetchData();
    });

    /// 监听扩展参数, 触发表格刷新
    watch(
      () => props.param,
      () => {
        fetchData();
      },
      { deep: true }
    );

    watch(
      () => props.columns,
      () => {
        state.columns = updateColumns(cloneDeep(props.columns))
      },
      { deep: true }
    )

    /// 改变按钮尺寸
    const changeSize = (target) => {
      state.size = target;
    };

    /// 表格打印
    const print = function () {
      let subOutputRankPrint = document.getElementById("pro-table");
      let newContent = subOutputRankPrint.innerHTML;
      let oldContent = document.body.innerHTML;
      document.body.innerHTML = newContent;
      window.print();
      window.location.reload();
      document.body.innerHTML = oldContent;
    };

    const handleRow = (row) => {
      context.emit('clickRow', row)
    }
    const onSearch = () => {
      fetchData()
    }
    return {
      state,
      /// 数据信息
      ...toRefs(state),
      /// 数据加载
      fetch: fetchData,
      /// 刷新方法
      reload,
      /// 过滤字段
      filtrationColumns,
      filtration,
      /// 选中字段
      onSelectChange,
      /// 改变大小
      changeSize,
      /// 打印
      print,
      handleRow,
      onSearch
    };
  },
});
</script>

<style lang="scss" scoped>
  .separate {
    padding: 5px;
  }
</style>
